package com.xdog.web3.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xdog.web3.config.Web3ConfigService;
import com.xdog.web3.exception.Web3ApiError;
import com.xdog.web3.exception.Web3ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * Web3 API工具类
 * 提供静态方法调用Web3 API，方便在任何地方使用
 */
@Slf4j
@Component
public class Web3ApiUtil {

    private static Web3ConfigService web3ConfigService;

    @Autowired
    public void setWeb3ConfigService(Web3ConfigService web3ConfigService) {
        Web3ApiUtil.web3ConfigService = web3ConfigService;
    }

    /**
     * 发送GET请求
     *
     * @param requestPath  请求路径
     * @param queryParams  查询参数对象
     * @return 响应结果
     */
    public static JSONObject get(String requestPath, Object queryParams) {
        // 构建完整URL
        StringBuilder urlBuilder = new StringBuilder(web3ConfigService.getBaseUrl());
        urlBuilder.append(requestPath);

        Map<String, String> paramsMap = convertObjectToMap(queryParams);
        if (paramsMap != null && !paramsMap.isEmpty()) {
            urlBuilder.append("?");
            boolean first = true;
            for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                if (entry.getValue() != null && !entry.getValue().isEmpty()) {
                    if (!first) {
                        urlBuilder.append("&");
                    }
                    urlBuilder.append(entry.getKey()).append("=").append(entry.getValue());
                    first = false;
                }
            }
        }

        String fullUrl = urlBuilder.toString();
        return executeRequest("GET", requestPath, fullUrl, null);
    }

    /**
     * 发送POST请求
     *
     * @param requestPath 请求路径
     * @param body        请求体
     * @return 响应结果
     */
    public static JSONObject post(String requestPath, Object body) {
        String fullUrl = web3ConfigService.getBaseUrl() + requestPath;
        String bodyStr = body != null ? JSON.toJSONString(body) : "";
        return executeRequest("POST", requestPath, fullUrl, bodyStr);
    }

    /**
     * 将对象转换为Map，过滤掉空值
     *
     * @param obj 对象
     * @return Map
     */
    private static Map<String, String> convertObjectToMap(Object obj) {
        if (obj == null) {
            return null;
        }

        Map<String, String> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();

        for (Field field : fields) {
            try {
                field.setAccessible(true);
                Object value = field.get(obj);
                if (value != null) {
                    map.put(field.getName(), value.toString());
                }
            } catch (IllegalAccessException e) {
                log.warn("无法访问字段: {}", field.getName(), e);
            }
        }

        return map;
    }

    /**
     * 执行HTTP请求的通用方法
     *
     * @param method     HTTP方法 (GET/POST)
     * @param requestPath 请求路径（用于签名）
     * @param fullUrl    完整URL
     * @param body       请求体（仅POST请求需要）
     * @return           响应结果
     */
    private static JSONObject executeRequest(String method, String requestPath, String fullUrl, String body) {
        try {
            log.info("准备发送Web3 {}请求: {}", method, fullUrl);

            URL url = new URL(fullUrl);

            // 创建HTTP连接，支持代理设置
            HttpURLConnection connection = createHttpConnection(url);

            connection.setRequestMethod(method);
            connection.setConnectTimeout(web3ConfigService.getConnectTimeout());
            connection.setReadTimeout(web3ConfigService.getReadTimeout());

            if ("POST".equals(method)) {
                connection.setDoOutput(true);
            }

            // 添加一些HTTP连接属性以提高兼容性
            connection.setRequestProperty("Connection", "close");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 设置请求头
            Map<String, String> headers = Web3SignatureUtils.generateAuthHeaders(
                    web3ConfigService.apiKey,
                    web3ConfigService.secretKey,
                    web3ConfigService.passphrase,
                    method,
                    requestPath,
                    body
            );

            for (Map.Entry<String, String> header : headers.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }

            // 写入请求体（仅POST请求）
            if ("POST".equals(method) && body != null) {
                try (OutputStream os = connection.getOutputStream()) {
                    byte[] input = body.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                }
            }

            // 读取响应
            int responseCode = connection.getResponseCode();
            log.info("Web3 {}请求响应码: {}", method, responseCode);

            // 读取响应内容
            StringBuilder response = new StringBuilder();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
                    responseCode >= 200 && responseCode < 300 ?
                            connection.getInputStream() :
                            connection.getErrorStream(),
                    StandardCharsets.UTF_8))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            }

            String responseStr = response.toString();

            // 解析响应结果
            JSONObject result = JSON.parseObject(responseStr);

            // 检查是否有错误码
            if (result.containsKey("code") && !result.getString("code").equals("0")) {
                String errorCode = result.getString("code");
                String errorMsg = result.getString("msg");
                Web3ApiError error = Web3ApiError.findByCode(errorCode);

                if (error != null) {
                    log.error("Web3 API返回错误: code={}, message={}, httpStatus={}",
                            errorCode, errorMsg, error.getHttpStatus());
                    throw new Web3ApiException(errorCode, error.getHttpStatus(),
                            "API错误: " + errorMsg);
                } else {
                    log.error("Web3 API返回未知错误: code={}, message={}", errorCode, errorMsg);
                    throw new Web3ApiException(errorCode, 400,
                            "API未知错误: " + errorMsg);
                }
            }

            log.info("Web3 {}请求处理完成", method);
            return result;
        } catch (Exception e) {
            log.error("Web3 API {}请求失败: {}", method, e.getMessage(), e);
            throw new RuntimeException("Web3 API请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建HTTP连接，支持代理设置
     *
     * @param url 目标URL
     * @return HttpURLConnection对象
     */
    private static HttpURLConnection createHttpConnection(URL url) {
        try {
            String proxyHost = web3ConfigService.getProxyHost();
            Integer proxyPort = web3ConfigService.getProxyPort();

            if (proxyHost != null && !proxyHost.isEmpty() && proxyPort != null) {
                log.debug("使用代理: {}:{}", proxyHost, proxyPort);
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
                return (HttpURLConnection) url.openConnection(proxy);
            } else {
                return (HttpURLConnection) url.openConnection();
            }
        } catch (Exception e) {
            throw new RuntimeException("创建HTTP连接失败: " + e.getMessage(), e);
        }
    }
}